package com.xcdh.ittools.service.impl;

import com.api.ittools.entity.Tables;
import com.api.ittools.entity.TablesColumn;
import com.api.ittools.entity.ToolProject;
import com.api.ittools.entity.ToolTpl;
import com.api.ittools.query.DbQuery;
import com.api.ittools.query.GeneratorQuery;
import com.api.ittools.vo.ProjectVo;
import com.api.ittools.vo.TablesVo;
import com.api.ittools.vo.TplVo;
import com.xcdh.commons.utils.DateUtils;
import com.xcdh.commons.utils.IFUtils;
import com.xcdh.commons.utils.StringUtil;
import com.xcdh.ittools.service.GeneratorCodeService;
import com.xcdh.ittools.service.ToolDatasourceService;
import com.xcdh.ittools.service.ToolProjectService;
import com.xcdh.ittools.service.ToolTplService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class GeneratorCodeServiceImpl implements GeneratorCodeService {
    @Autowired
    private ToolDatasourceService toolDatasourceService ;
    @Autowired
    private ToolProjectService toolProjectService ;
    @Autowired
    private ToolTplService toolTplService ;


    @Override
    public ProjectVo buildToolTpl(GeneratorQuery query) {
        //数据链接
        DbQuery db = DbQuery.builder().dsId(query.getDsId())
                .build();
        // 获取项目对应模板
        ToolProject toolProject = toolProjectService.getById(query.getProjectId());
        // 需要生成代码的表
        List<String> tableNames = query.getTableName();
        List<TablesVo> tablesVos = new ArrayList<>(tableNames.size()) ;
        for (String tableName : tableNames) {
            db.setTableName(tableName);
            // 获取表信息
            Tables table = toolDatasourceService.getTable(db);
            //获取表的字段名称
            List<TablesColumn> columnList = toolDatasourceService.queryColumnList(db);
            columnList.forEach(col->col.setMapUnderscoreToCamelCase(toolProject.getMapUnderscoreToCamelCase()));
            // 代码模板
            List<ToolTpl> templates = toolTplService.findTplByProjectId(query.getProjectId());
            List<TplVo> tplVoList = new ArrayList<>(templates.size()) ;
            for (ToolTpl template : templates) {
                StringWriter sw = new StringWriter();
                //设置参数
                Map<String, Object> objectMap = toPrams(toolProject, table, columnList , template);
                VelocityContext context = new VelocityContext(objectMap);
                Velocity.evaluate(context, sw, "template", template.getTpl());
                String fileName = getFileName(template, table, toolProject);
                tplVoList.add(new TplVo(template.getTplName() , sw.toString() , fileName)) ;
                IOUtils.closeQuietly(sw);
            }
            tablesVos.add(new TablesVo(tableName , tplVoList)) ;
        }
        return new ProjectVo(toolProject.getProjectTitle() , tablesVos) ;
    }

    public  String getFileName(ToolTpl template, Tables tables , ToolProject toolProject){
        String packageName = IFUtils.nvlString(toolProject.getPackageName() , "com.it.xcdh");
        StringBuilder builder = new StringBuilder() ;
        StringBuilder packs = new StringBuilder() ;
        for (String s : packageName.split("\\.")) {
            builder.append(s).append(File.separator) ;
        }
        packageName = builder.toString() ;
        String pack = IFUtils.nvlString(template.getFolder() , "entity") ;
        for (String s : pack.split("/")) {
            packs.append(s).append(File.separator) ;
        }
        pack = packs.toString() ;
        String className = tableToJava(tables.getTableName(), toolProject.getTablePrefix());
        return packageName  + pack.toLowerCase()  + className + template.getClassSuffix() + "."+template.getSuffix();
    }

    private Map<String,Object> toPrams(ToolProject toolProject ,
                                       Tables tables ,
                                       List<TablesColumn> columns,
                                       ToolTpl template){
        Map<String, Object> map = new HashMap<>(10);
        String packageName = IFUtils.nvlString(toolProject.getPackageName(), "com.it.xcdh");
        String className = StringUtil.toHump(tableToJava(tables.getTableName() , toolProject.getTablePrefix()));
        String beanName = className + template.getClassSuffix() ;
        TablesColumn priMaryKey = findPriMaryKey(columns);
        map.put("tableName", tables.getTableName());// 表名
        map.put("comments", tables.getTableComment());//表描述
        map.put("PRI", priMaryKey);// 表主键
        map.put("className", className);//类名
        map.put("classname", StringUtil.firstLower(className));//类名
        map.put("beanName", beanName) ;
        map.put("package", packageName);//包名
        map.put("classSuffix",template.getClassSuffix());//类前缀
        map.put("pathName", packageName.substring(toolProject.getPackageName().lastIndexOf(".") + 1));//包路劲
        map.put("columns", columns);// 字段
        map.put("author", toolProject.getAuthor());//作者
        map.put("email", toolProject.getEmail());// 邮箱
        map.put("mapUnderscoreToCamelCase",toolProject.getMapUnderscoreToCamelCase() ) ;
        map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));//时间
        return  map ;
    }

    private TablesColumn findPriMaryKey(List<TablesColumn> columns){
        List<TablesColumn> priColumn = columns.stream().filter(col -> col.isPrimary()).collect(Collectors.toList());
        if(priColumn.size() >0){
            return priColumn.get(0) ;
        }
        return columns.get(0) ;
    }

    public  String tableToJava(String tableName, String tablePrefix) {
        if(StringUtils.isNoneBlank(tablePrefix)){
            tableName = tableName.substring(tableName.indexOf("_") + 1);
        }else{
            tableName = tableName.replace(tablePrefix, "");
        }
        return columnToJava(tableName);
    }
    public  String columnToJava(String columnName) {
        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
    }

    public static void main(String[] args) {

    }
}
